﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;

namespace LdCms.Web.Services
{
    using LdCms.EF.DbStoredProcedure;
    using LdCms.Common.Json;
    using LdCms.Common.Extension;
    using LdCms.EF.DbModels;
    using LdCms.IBLL.Log;
    using LdCms.IBLL.Sys;
    using LdCms.Common.Net;
    using LdCms.IBLL.Member;

    /// <summary>
    /// WebApi访问日志操作服务类
    /// 
    /// 
    /// 
    /// </summary>
    public class ApiRecordManager: IApiRecordManager
    {
        private readonly IHttpContextAccessor Accessor;
        private readonly IInterfaceAccountService InterfaceAccountService;
        private readonly IInterfaceAccessTokenService InterfaceAccessTokenService;
        private readonly IAccountAccessTokenService AccountAccessTokenService;
        private readonly IWebApiAccessRecordService SysWebApiAccessRecordService;
        public ApiRecordManager(IHttpContextAccessor Accessor, IInterfaceAccountService InterfaceAccountService, IInterfaceAccessTokenService InterfaceAccessTokenService, IAccountAccessTokenService AccountAccessTokenService, IWebApiAccessRecordService SysWebApiAccessRecordService)
        {
            this.Accessor = Accessor;
            this.InterfaceAccountService = InterfaceAccountService;
            this.InterfaceAccessTokenService = InterfaceAccessTokenService;
            this.AccountAccessTokenService = AccountAccessTokenService;
            this.SysWebApiAccessRecordService = SysWebApiAccessRecordService;
        }
        private int SystemID = BaseSystemConfig.SystemID;

        public long Save(string token)
        {
            try
            {
                return Save(token, "");
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public long Save(string token, string sParams)
        {
            try
            {
                return SaveWebApiAccessRecord(token, sParams);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public long Save(string token, object formValue)
        {
            try
            {
                string sParams = formValue.ToJson();
                return Save(token, sParams);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public bool Update(long id, string result, bool state)
        {
            try
            {
                if (id <= 0)
                    return false;
                return SysWebApiAccessRecordService.UpdateWebApiAccessRecordState(id, result, state);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        private long SaveWebApiAccessRecord(string token, string sParams)
        {
            try
            {
                string url = Accessor.HttpContext.Request.GetAbsoluteUri();
                string method = Accessor.HttpContext.Request.GetHttpMethod();
                string version = string.Empty;
                string controllerName = string.Empty;
                string actionName = "index";
                string methodName = "";
                string[] arrUrl = url.Split('?')[0].Split('/');
                if (arrUrl.Length >= 5)
                    version = arrUrl[4].ToLower();
                if (arrUrl.Length >= 6)
                    controllerName = arrUrl[5].ToLower();
                if (arrUrl.Length >= 7)
                    actionName = arrUrl[6].ToLower();
                if (arrUrl.Length >= 8)
                    methodName = arrUrl[7].ToLower();

                TokenType tokenType = GetTokenType(token);
                var TokenIdentityAccount = GetTokenIdentityAccount(token);
                if (TokenIdentityAccount == null)
                    throw new Exception("get interface account fail！");

                string companyId = TokenIdentityAccount.CompanyID;
                string account = TokenIdentityAccount.Account;
                var entity = new Ld_Log_WebApiAccessRecord()
                {
                    SystemID = SystemID,
                    CompanyID = companyId,
                    Account = account,
                    ClassID = (byte)tokenType,
                    ClassName = tokenType.ToString(),
                    Method = method,
                    Url = url,
                    Params = sParams,
                    Version = version,
                    ControllerName = controllerName,
                    ActionName = actionName,
                    MethodName = methodName,
                    Result = null,
                    IpAddress = Net.Ip,
                    State = false,
                    CreateDate = DateTime.Now
                };
                var result = SysWebApiAccessRecordService.SaveWebApiAccessRecord(entity);
                return result ? entity.ID : 0;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private TokenType GetTokenType(string token)
        {
            try
            {
                int tokenTotalLength = token.Length;
                int[] arrToken = new int[] { 16, 32, 48, 64, 128 };
                if (!arrToken.Contains(tokenTotalLength))
                    throw new Exception("appid uuid token params invalid！");
                switch (tokenTotalLength)
                {
                    case 16:
                        return TokenType.AppID;
                    case 32:
                        return TokenType.Uuid;
                    case 48:
                        return TokenType.Member;
                    case 64:
                        return TokenType.Staff;
                    case 128:
                        return TokenType.Token;
                    default:
                        return TokenType.Sys;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        private SP_Get_Sys_InterfaceAccountByToken_V1 GetTokenIdentityAccount(string token)
        {
            try
            {
                return InterfaceAccountService.GetInterfaceAccessTokenV1Pro(SystemID, token);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public enum TokenType
        {
            Sys = 1,
            AppID = 16,
            Uuid = 32,
            Member = 48,
            Staff = 64,
            Token = 128
        }
        
    }
}
